﻿using Newtonsoft.Json;
using System.ComponentModel;
using System.Windows;
using VisionDesigner;
using VisionDesigner.PositionFix;
using VM.Common.Enums;
using VM.Common.EventMgrLib;
using VM.Common.Helper;
using VM.Dialogs.Views;
using VM.Start.Attributes;
using VM.Start.Common;
using VM.Start.Core;
using VM.Start.Events;
using VM.Start.Models;
using VM.Start.ViewModels;

namespace Plugin.PositionFix
{
    [Serializable]
    public enum SelectTypeEnum
    {
        按点,
        按坐标
    }

    [Serializable]
    public enum eLinkCommand
    {
        CHPFeatureMatch_Point,
        CHPFeatureMatch_X,
        CHPFeatureMatch_Y,
        CHPFeatureMatch_Angle,
        CHPFeatureMatch_XScale,
        CHPFeatureMatch_YScale
    }

    [Category("检测识别")]
    [DisplayName("位置修正")]
    [ModuleImageName("PositionFix")]
    [JsonObject(MemberSerialization.OptOut)]
    public class PositionFixViewModel : ModuleBase
    {
        public PositionFixViewModel()
        {
            try
            {
                if (PositionFixTool == null)
                {
                    PositionFixTool = new CPositionFixTool();
                }
                BasicParam = PositionFixTool.BasicParam;
            }
            catch (MvdException ex)
            {
                if (ex.ErrorCode == MVD_ERROR_CODE.MVD_E_RUNTIME)
                {
                    MessageView.Ins.MessageBoxShow("运行环境异常，请检测加密狗！", eMsgType.Error);
                }
                else
                {
                    MessageView.Ins.MessageBoxShow("创建实例失败！", eMsgType.Error);
                }
            }

        }
        #region 属性


        public CPositionFixTool PositionFixTool = null;
        public VisionDesigner.PositionFix.MVD_FIDUCIAL_POINT_F stBasinInit = new VisionDesigner.PositionFix.MVD_FIDUCIAL_POINT_F();
        public VisionDesigner.PositionFix.MVD_FIDUCIAL_POINT_F stBasicRun = new VisionDesigner.PositionFix.MVD_FIDUCIAL_POINT_F();
        public CPositionFixBasicParam BasicParam = null;
        #endregion
        #region 数据接口
        /// <summary>
        /// 选择方式
        /// </summary>
        private SelectTypeEnum _SelectType = SelectTypeEnum.按点;
        public SelectTypeEnum SelectType
        {
            get { return _SelectType; }
            set
            {
                Set(ref _SelectType, value, new Action(() =>
                {
                    switch (_SelectType)
                    {
                        case SelectTypeEnum.按点:
                            PointVisible = Visibility.Visible;
                            CoordinateVisible = Visibility.Collapsed;
                            break;
                        case SelectTypeEnum.按坐标:
                            PointVisible = Visibility.Collapsed;
                            CoordinateVisible = Visibility.Visible;
                            break;
                        default:
                            break;
                    }
                }));
            }
        }

        private Visibility _PointVisible = Visibility.Visible;
        public Visibility PointVisible
        {
            get { return _PointVisible; }
            set { Set(ref _PointVisible, value); }
        }

        private Visibility _CoordinateVisible = Visibility.Collapsed;
        public Visibility CoordinateVisible
        {
            get { return _CoordinateVisible; }
            set { Set(ref _CoordinateVisible, value); }
        }

        /// <summary>
        /// 原点链接文本
        /// </summary>
        public string _MatchPoint;
        public string MatchPoint
        {
            get { return _MatchPoint; }
            set { Set(ref _MatchPoint, value); }
        }

        /// <summary>
        /// 原点X链接文本
        /// </summary>
        public string _MatchPointX;
        public string MatchPointX
        {
            get { return _MatchPointX; }
            set { Set(ref _MatchPointX, value); }
        }

        /// <summary>
        /// 原点Y链接文本
        /// </summary>
        public string _MatchPointY;
        public string MatchPointY
        {
            get { return _MatchPointY; }
            set { Set(ref _MatchPointY, value); }
        }

        /// <summary>
        /// 角度链接文本
        /// </summary>
        public string _MatchAngle;
        public string MatchAngle
        {
            get { return _MatchAngle; }
            set { Set(ref _MatchAngle, value); }
        }

        /// <summary>
        /// X尺度方向链接文本
        /// </summary>
        public string _MatchXScale;
        public string MatchXScale
        {
            get { return _MatchXScale; }
            set { Set(ref _MatchXScale, value); }
        }

        /// <summary>
        /// Y尺度方向链接文本
        /// </summary>
        public string _MatchYScale;
        public string MatchYScale
        {
            get { return _MatchYScale; }
            set { Set(ref _MatchYScale, value); }
        }

        #endregion
        #region 指令
        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _LinkCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase LinkCommand
        {
            get
            {
                if (_LinkCommand == null)
                {
                    //以GUID+类名作为筛选器
                    EventMgr.Ins
                        .GetEvent<VarChangedEvent>()
                        .Subscribe(OnVarChanged, o => o.SendName.StartsWith($"{ModuleGuid}"));
                    _LinkCommand = new CommandBase(
                        (obj) =>
                        {
                            eLinkCommand linkCommand = (eLinkCommand)obj;
                            switch (linkCommand)
                            {
                                case eLinkCommand.CHPFeatureMatch_Point:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchPoint"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchPoint");
                                    break;
                                case eLinkCommand.CHPFeatureMatch_X:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchPointX"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchPointX");
                                    break;
                                case eLinkCommand.CHPFeatureMatch_Y:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchPointY"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchPointY");
                                    break;
                                case eLinkCommand.CHPFeatureMatch_Angle:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchAngle"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchAngle");
                                    break;
                                case eLinkCommand.CHPFeatureMatch_XScale:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchXScale"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchXScale");
                                    break;
                                case eLinkCommand.CHPFeatureMatch_YScale:
                                    CommonMethods.GetModuleList(
                                        ModuleParam,
                                        VarLinkViewModel.Ins.Modules,
                                        "MatchYScale"
                                    );
                                    EventMgr.Ins
                                        .GetEvent<OpenVarLinkViewEvent>()
                                        .Publish($"{ModuleGuid},MatchYScale");
                                    break;
                                default:
                                    break;
                            }
                        }
                    );
                }
                return _LinkCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _CreateBasicPoint;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase CreateBasicPoint
        {
            get
            {
                if (_CreateBasicPoint == null)
                {
                    _CreateBasicPoint = new CommandBase((obj) =>
                    {
                        if (stBasicRun.stPosition.fX == 0 && stBasicRun.stPosition.fY == 0
                        && stBasicRun.fScaleX == 0 && stBasicRun.fScaleY == 0 && stBasicRun.fAngle == 0)
                        {
                            MessageView.Ins.MessageBoxShow("基准点创建失败！", eMsgType.Warn);
                        }
                        else
                        {
                            stBasinInit = stBasicRun;
                            BasicParam.BasePoint = stBasinInit;
                            MessageView.Ins.MessageBoxShow("基准点创建成功！", eMsgType.Success);
                        }
                    });
                }
                return _CreateBasicPoint;
            }
        }
        #endregion
        #region 方法
        public override void Loaded()
        {
            base.Loaded();
            if (ModuleView is PositionFixView)
            {
                ClosedView = true;
                SetDefaultLink();
            }
        }

        public override void SetDefaultLink()
        {
            CommonMethods.GetModuleList(ModuleParam, VarLinkViewModel.Ins.Modules, "Image");
            var moduls = VarLinkViewModel.Ins.Modules.LastOrDefault();
            if (moduls?.VarModels.Count > 0)
            {
                var imagetext = $"&{moduls.DisplayName}.{moduls.VarModels[0].Name}";
                if (imagetext != null)
                {
                    VarModel var = Prj.GetParamByName(imagetext);
                    if (var == null)
                        return;
                    object image = var.Value;
                    if (image == null)
                        return;
                    if (image is CMvdImage)
                    {
                        DispImage = (CMvdImage)image;
                    }
                }
            }

            string[] matchParams = { "MatchPoint", "MatchPointX", "MatchPointY", "MatchAngle", "MatchXScale", "MatchYScale" };
            Action<string, Action<string>> setLink = (param, assignAction) =>
            {
                CommonMethods.GetModuleList(ModuleParam, VarLinkViewModel.Ins.Modules, param);
                var module = VarLinkViewModel.Ins.Modules.LastOrDefault();
                if (module?.VarModels.Count > 0)
                    assignAction($"&{module.DisplayName}.{module.VarModels[0].Name}");
            };
            if (MatchPoint == null)
            {
                setLink("MatchPoint", link => MatchPoint = link);
            }
            if (MatchPointX == null)
            {
                setLink("MatchPointX", link => MatchPointX = link);
            }
            if (MatchPointY == null)
            {
                setLink("MatchPointY", link => MatchPointY = link);
            }
            if (MatchAngle == null)
            {
                setLink("MatchAngle", link => MatchAngle = link);
            }
            if (MatchXScale == null)
            {
                setLink("MatchXScale", link => MatchXScale = link);
            }
            if (MatchYScale == null)
            {
                setLink("MatchYScale", link => MatchYScale = link);
            }
            UpdateMatchPoint(MatchPoint);
            UpdateMatchPointX(MatchPointX);
            UpdateMatchPointY(MatchPointY);
            UpdateMatchAngle(MatchAngle);
            UpdateMatchXScale(MatchXScale);
            UpdateMatchYScale(MatchYScale);
            if (stBasinInit.stPosition.fX == 0 && stBasinInit.stPosition.fY == 0
                && stBasinInit.fScaleX == 0 && stBasinInit.fScaleY == 0 && stBasinInit.fAngle == 0)
            {
                stBasinInit = stBasicRun;
                if (BasicParam != null)
                {
                    BasicParam.BasePoint = stBasinInit;
                }
                else
                {
                    MessageView.Ins.MessageBoxShow("运行环境异常，请检测加密狗！", eMsgType.Error);
                }
            }
        }

        private void OnVarChanged(VarChangedEventParamModel obj)
        {
            var updateActions = new Dictionary<string, Action<string>>
            {
                { "MatchPoint", UpdateMatchPoint },
                { "MatchPointX", UpdateMatchPointX },
                { "MatchPointY", UpdateMatchPointY },
                { "MatchAngle", UpdateMatchAngle },
                { "MatchXScale", UpdateMatchXScale },
                { "MatchYScale", UpdateMatchYScale }
            };

            var key = obj.SendName.Split(',')[1];
            if (updateActions.TryGetValue(key, out var updateAction) && obj.LinkName != null)
            {
                updateAction(obj.LinkName);
            }
        }

        private void UpdateParameter<T>(string paramName, Action<T> updateAction)
        {
            if (string.IsNullOrWhiteSpace(paramName)) return;

            var varModel = Prj.GetParamByName(paramName);
            if (varModel?.Value is T value)
            {
                updateAction(value);
                BasicParam.RunningPoint = stBasicRun; // 更新 BasicParam.RunningPoint
            }
        }

        public void UpdateMatchPoint(string matchPoint) =>
            UpdateParameter(matchPoint, (MVD_POINT_F point) => stBasicRun.stPosition = point);

        public void UpdateMatchPointX(string matchPointX) =>
            UpdateParameter(matchPointX, (float x) => stBasicRun.stPosition.fX = x);

        public void UpdateMatchPointY(string matchPointY) =>
            UpdateParameter(matchPointY, (float y) => stBasicRun.stPosition.fY = y);

        public void UpdateMatchAngle(string matchAngle) =>
            UpdateParameter(matchAngle, (float angle) => stBasicRun.fAngle = angle);

        public void UpdateMatchXScale(string matchXScale) =>
            UpdateParameter(matchXScale, (float xScale) => stBasicRun.fScaleX = xScale);

        public void UpdateMatchYScale(string matchYScale) =>
            UpdateParameter(matchYScale, (float yScale) => stBasicRun.fScaleY = yScale);

        public override bool ExeModule()
        {
            SetDefaultLink();
            if (PositionFixTool == null || PositionFixTool.BasicParam.BasePoint.fScaleX == 0 && PositionFixTool.BasicParam.BasePoint.fScaleY == 0 &&
                PositionFixTool.BasicParam.RunningPoint.fScaleX == 0 && PositionFixTool.BasicParam.RunningPoint.fScaleY == 0)
            {
                ChangeModuleRunStatus(eRunStatus.NG);
                return false;
            }
            MVD_SIZE_I stImageSize = new MVD_SIZE_I();
            stImageSize.nWidth = (int)DispImage.Width;
            stImageSize.nHeight = (int)DispImage.Height;
            BasicParam.RunImageSize = stImageSize;
            BasicParam.FixMode = MVD_POSFIX_MODE.MVD_POSFIX_MODE_HVA;
            ChangeModuleRunStatus(eRunStatus.OK);
            return true;

        }

        public override bool ExeModule(string TemplateName)
        {
            return ExeModule();
        }

        /// <summary>
        /// 添加结果
        /// </summary>
        public override void AddOutputParams()
        {
            base.AddOutputParams();
            AddOutputParam("位置修正信息", "CPositionFixTool", PositionFixTool);
        }

        #endregion

    }
}
